package jwcb.hire.message.service;

import jwcb.hire.common.core.utils.StringUtil;
import jwcb.hire.common.core.utils.TimestampUtil;
import jwcb.hire.common.core.utils.VerifyUtil;
import jwcb.hire.common.domain.constants.MessageConstants;
import jwcb.hire.common.domain.domain.ResultCode;
import jwcb.hire.common.domain.exception.ServiceException;
import jwcb.hire.common.redis.RedisService.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 短信验证服务
 */
@RefreshScope
@Component
public class CaptchaService {

    /**
     * redis服务类
     */
    @Autowired
    private RedisService redisService;

    /**
     * 单个手机号，每日发送短信次数的限制
     */
    @Value("${sms.send-limit:}")
    private Integer sendLimit;

    /**
     * 验证码的有效期，单位是分钟
     */
    @Value("${sms.code-expiration:}")
    private Long phoneCodeExpiration;

    /**
     * 用来判断是否发送随机验证码
     */
    @Value("${sms.send-message:false}")
    private boolean sendMessage;

    /**
     * 阿里云短信服务
     */
    @Autowired
    private AliSmsService aliSmsService;

    /**
     * 发送验证码
     * @param phone 手机号
     * @return 验证码
     */
    public String sendCode(String phone) {
        String limitCacheKey = MessageConstants.SMS_CODE_TIMES_KEY + phone;
        Integer times = redisService.getCacheObject(limitCacheKey, Integer.class);
        times = times == null ? 0 : times;
        if (times > sendLimit) {
            throw new ServiceException(ResultCode.SEND_MSG_OVERLIMIT);
        }

        String codeKey = MessageConstants.SMS_CODE_KEY + phone;
        long expire = redisService.getExpire(codeKey);
        if(expire >= phoneCodeExpiration * 60 - 60) {
            long time = expire - (phoneCodeExpiration * 60 - 60);
            throw new ServiceException("操作频繁， 请在"+ time+ "秒之后再试", ResultCode.INVALID_PARA.getCode());
        }
        String verifyCode = sendMessage ? VerifyUtil.generateVerifyCode(MessageConstants.DEFAULT_SMS_LENGTH) : MessageConstants.DEFAULT_SMS_CODE;
        if (sendMessage) {
            boolean result = aliSmsService.sendMobileCode(phone, verifyCode);
            if (!result) {
                throw new ServiceException(ResultCode.SEND_MSG_FAILED);
            }
        }
        redisService.setCacheObject(codeKey, verifyCode, phoneCodeExpiration, TimeUnit.MINUTES);
        long seconds = TimestampUtil.calculateDifferenceMillis(System.currentTimeMillis(),TimestampUtil.getNextDayMidnightMillSeconds());
        redisService.setCacheObject(limitCacheKey, times + 1, seconds, TimeUnit.MILLISECONDS);
        return verifyCode;
    }

    /**
     * 从缓存中获取手机号的验证码
     * @param phone 手机号
     * @return 验证码
     */
    public String getCode(String phone) {
        String cacheKey = MessageConstants.SMS_CODE_KEY + phone;
        return redisService.getCacheObject(cacheKey, String.class);
    }

    /**
     * 从缓存中删除手机号的验证码
     * @param phone 手机号
     * @return 验证码
     */
    public boolean deleteCode(String phone) {
        String cacheKey = MessageConstants.SMS_CODE_KEY + phone;
        return redisService.deleteObject(cacheKey);
    }

    /**
     * 校验手机号与验证码是否匹配
     * @param phone 手机号
     * @param code 验证码
     * @return 布尔类型
     */
    public boolean checkCode(String phone, String code) {
        if (getCode(phone) == null || StringUtil.isEmpty(getCode(phone))) {
            throw new ServiceException(ResultCode.INVALID_CODE);
        }
        return getCode(phone).equals(code);
    }
}
